#include <string.h>
#include <stdlib.h>
#include "../q_common.h"
#include "qi_grammar.h"


/* all tokens */
struct qi_grammarplaceholder* qi_grammar[Q_HASH_TABLE_SIZE];


void qi_initgrammar()
{
	memset(qi_grammar, 0, sizeof(qi_grammar));
}


struct qi_grammarplaceholder* qi_grammarplaceholderlookup(const char* const name)
{
	struct qi_grammarplaceholder* tmp;
	if(!name)
		return NULL;

	tmp = qi_grammar[q_hashname(name)];
	for(; tmp; tmp = tmp->next)
		if(!strncmp(tmp->name, name, Q_MAX_SYMBOL_LENGTH))
			return tmp;
	return NULL;
}

int qi_addgrammarleaf(const char* const name, int (*validate)(const char* const str), int (*dominating_branch)(const char* const str))
{
	int hash;
	struct qi_grammarplaceholder* tmp;
	if(!name)
		return Q_STATUS_FATAL;
	if(qi_grammarplaceholderlookup(name))
		return Q_STATUS_ALREADYEXISTS;
	if(!(tmp = (struct qi_grammarplaceholder*)malloc(sizeof(struct qi_grammarplaceholder))))
		return Q_STATUS_FATAL;
	hash = q_hashname(name);
	strncpy(tmp->name, name, Q_MAX_SYMBOL_LENGTH);
	tmp->type = GRAMMAR_LEAF;
	tmp->leaf.validate = validate;
	tmp->leaf.dominating_branch = dominating_branch;
	tmp->next = qi_grammar[hash];
	qi_grammar[hash] = tmp;
	return Q_STATUS_OK;
}

int qi_addgrammarnode(const char* const name, enum qi_grammarnodetype type)
{
	int hash;
	struct qi_grammarplaceholder* tmp;
	if(!name)
		return Q_STATUS_FATAL;
	if(qi_grammarplaceholderlookup(name))
		return Q_STATUS_ALREADYEXISTS;
	if(!(tmp = (struct qi_grammarplaceholder*)malloc(sizeof(struct qi_grammarplaceholder))))
		return Q_STATUS_FATAL;
	hash = q_hashname(name);
	strncpy(tmp->name, name, Q_MAX_SYMBOL_LENGTH);
	tmp->type = GRAMMAR_NODE;
	tmp->node.type = type;
	tmp->node.num_children = tmp->node.current_children = 0;
	tmp->node.child = NULL;
	tmp->next = qi_grammar[hash];
	qi_grammar[hash] = tmp;
	return Q_STATUS_OK;
}

int qi_addtogrammarnode(const char* const parent, const char* const child, int min, int max)
{
	struct qi_grammarplaceholder *pptr, *cptr;
	struct qi_grammarchild *childptr, *last;
	if(!parent || !child || !(pptr = qi_grammarplaceholderlookup(parent)) || !(cptr = qi_grammarplaceholderlookup(child)) ||
	   (pptr->type != GRAMMAR_NODE) || !(childptr = (struct qi_grammarchild*)malloc(sizeof(struct qi_grammarchild))))
		return Q_STATUS_FATAL;

	++pptr->node.num_children;
	childptr->ptr = cptr;
	childptr->min = min;
	childptr->max = max;
	childptr->next = NULL;
	if(!pptr->node.child)
		pptr->node.child = childptr;
	else
	{
		for(last = pptr->node.child; last->next; last = last->next);
		last->next = childptr;
	}
	return Q_STATUS_OK;
}


